#ifndef _DETECTION_MODEL_
#define _DETECTION_MODEL_

#include "SquareDetect_API.h"


typedef struct deflate_sample_data
{
	int down_sample_rate_2;
	int down_sample_move_2;
	float deflate_rate;
	float total_deflate_rate;
}PYRAMID_SAMPLE_STRUCT;


typedef struct SDPOINT
{
    long  x;
    long  y;
} SDPOINT;

//检测的特征描述
struct DETECT_DATA
{
	DECTRECT square_rect;
	int scale;
	int weight;//当前的权重数据//通过最后几级的都有权重，级数越大，权重越大
	float conf;
};

#define LAB_BLOCK_FEAT_NUM 8
#define LAB_HISTO_DIM (1<<LAB_BLOCK_FEAT_NUM)


typedef struct deflate_image_data
{
	int ori_ht, ori_wd;
	float cur_rate;
	int cur_ht, cur_wd;
	unsigned char **cur_image;
	int **sum_image, **sqr_image;
	int **rate_image;
	int **fine_sum_image;
	char **process_flag;
}DEFLATE_IMAGE;

//LAB block number
#define FD16_LAB_BLOCK_FEAT_NUM 8
//Histogram dimension of LAB feature
#define FD16_LAB_HISTO_DIM (1<<FD16_LAB_BLOCK_FEAT_NUM)

//One trained Adaboost weak classifier
typedef struct FD16_fastadaboost_feature_train_detect_param_one_block_small_size
{
	unsigned short cen_feat_num;
	unsigned short neigh_feat_num[FD16_LAB_BLOCK_FEAT_NUM];
	signed char lab_histo[FD16_LAB_HISTO_DIM];//The trained histogram for the current LAB feature
}FD16_FAST_ADABOOST_DETECT_PARAM_FIRST_CHAR;

//The trained Adaboost strong classifier of one level
typedef struct FD16_fast_level_detect_model_one_block_small_size
{
	int n_step;//the weak classifier number
	int alpha_thres;//the final threshold for this strong classifier
	FD16_FAST_ADABOOST_DETECT_PARAM_FIRST_CHAR *pModel;//the weak classifier
}FD16_FAST_DETECT_MODEL_FIRST_CHAR;



//Adaboost算法单特征训练检测数据
typedef struct fastadaboost_feature_train_detect_param_one_block
{
	unsigned char left, top;
	unsigned char feat_flag;
	unsigned char null_char;
	unsigned char neigh_left[LAB_BLOCK_FEAT_NUM], neigh_top[LAB_BLOCK_FEAT_NUM];
	unsigned char neigh_feat_flag[LAB_BLOCK_FEAT_NUM];
	float lab_histo[LAB_HISTO_DIM];
}FAST_ADABOOST_DETECT_PARAM_FIRST;

//各级快速检测模型
typedef struct fast_level_detect_model_one_block
{
	int n_step;//当前步数
	float alpha_thres;//Adaboost所有特征alpha和的判决门限
	FAST_ADABOOST_DETECT_PARAM_FIRST *pModel;//各级特征模型	
}FAST_DETECT_MODEL_FIRST;

typedef struct DETECT_PARAMETERS
{	
	int detect_start_search_scale_num;// the minimal scale number, [0-24]
	int detect_end_search_scale_num;//the maximum scale number,[0-24]
	
	//The two parameters control the face detection accuracy and false accepted rate
	//larger thresholds mean lower face detection accuracy and lower false accepted rate
	//the default thresholds are "Candidate_Combine_Weight_MinThres = 2, Candidate_Combine_Conf_MinThres = 0"
	int Candidate_Combine_Weight_MinThres;//threshold of the combined weight, only faces combined with more candidate faces will be returned, [0, 4]
	int Candidate_Combine_Conf_MinThres;//thredhos of the combined confidence, only faces with larger combined confidence will be returned, [-1024, 1024]
	
	
	int FastSearch_DetectLevel;//The separating level for optimization, [0, 21]
	int Detect_Search_XShift;//X search shift [1, 4]
	int Detect_Search_YShift;//Y search shift [1, 4]

}DETECT_PARAM;

class CDetectModelCls
{
public:
	CDetectModelCls();
	CDetectModelCls(int nDetectLevel);
	~CDetectModelCls();

	FAST_DETECT_MODEL_FIRST *pFastDetectModel;
	FD16_FAST_DETECT_MODEL_FIRST_CHAR *FD16_pFastDetectModelTemp;
private:
	PYRAMID_SAMPLE_STRUCT *pSampleRate;
	int m_nDetectLevel;
	int nrate;
	int m_detect_end_search_scale_num;
	int m_detect_start_search_scale_num;
	
	int m_Candidate_Combine_Weight_MinThres;
	int m_Candidate_Combine_Conf_MinThres;
	int m_Detect_Search_XShift;
	int m_Detect_Search_YShift;

public:
	bool LoadDetectModel();
	bool LoadDetectModel(const char *filename);
	void SetDetectParam(DETECT_PARAM *pDetectParam);

	bool JudgeCandidateRectImage_Single(FAST_DETECT_MODEL_FIRST *pFeatModel, int wd, int ht, 
											int **block_sum, int x, int y, float *conf);
	int FastCalOneLabFeat_Single(FAST_ADABOOST_DETECT_PARAM_FIRST *pModel,
											int wd, int ht, int x, int y, int **block_sum_ptr);
	int CombineDetectedObjs(DETECT_DATA *pSquarePos, int nface);

	int FastDetectAllSquarePosition_All(unsigned char **image, int ht, int wd, DETECT_DATA *pSquarePos);
	void GetBlockSumHaarData_All(int **block_sum_data, int **sum_image, int wd, int ht);
	void GetBlockLABData_all(int **block_sum_data, int **total_lab_data, int wd, int ht);
	bool JudgeCandidateRectImage(int **lab_data, int cur_level,
												  int rect_wd, int rect_ht, int x, int y, float &conf);
	bool JudgeCandidateRectImage_LAB(FAST_DETECT_MODEL_FIRST *pFeatModel, int wd, int ht, 
											int **lab_sum, int x, int y, float *conf, float prev_conf);

	
};

void FreeArray_int(int **array, int row, int col);
int GetRectSumImage_Fast(int **sum_image, int top, int left, int bottom, int right);
void GetSumImages(int **image, int **sum_image, int wd, int ht);
void GetSumImages(unsigned char **image, int **sum_image, int wd, int ht);
unsigned char **f2b (int nr, int nc);
int **f2i (int nr, int nc);
void FreeArray_BYTE(unsigned char **array, int row, int col);
void BilinearResizeImage_Down2( unsigned char ** pSrc, unsigned char ** pDes, int oriwd, int oriht, int deswd, int desht,
							   int down_rate, int down_move);

SDPOINT GetRectMidPoint(DECTRECT rect);

SDPOINT GetSDPoint(int x,int y);

float getDot2LineDist(SDPOINT pt, float line[4]);

void sortRect(DECTRECT *rect,SDPOINT *point,int n);

bool JudgeDotInRect(DECTRECT rect,SDPOINT point);

DECTRECT GetSubRect(DECTRECT);

void sortRectXY(DECTRECT *rect,int n,int m);

#endif